﻿#include "../../ctlSlider.h"

namespace swui
{
	bool ctlSlider::create(ctlRoot* parent, ctlRect rect, 
		unsigned buttonSize, ctlScrollDirection dir, const ctlStyleProgress& style)
	{
		if(parent == 0 || isCreated() || !parent->isCreated()) return false; 
		std::lock_guard<decltype(_eventTrans)> gurad(
			_eventTrans.getControlEventTrans(parent));
		ctlProgress::create(parent, rect, dir, style);
		_control_virtual_class_end = this;
		_controlType = ctlControlType::ctlSlider;
		_slider_button.enableRound(true);
		_slider_button.setRoundRadius(100);
		_slider_button.enableDrag(true);
		ctlStyleGradient::_subType stytype = ctlStyleGradient::common;
		switch(style.subStyle)
		{
		case ctlStyleProgress::orange:
			stytype = ctlStyleGradient::orange;
			break;
		}
		if(getBarDirection() == ctlScrollDirection::horizontal)
		{
			_slider_button.create(parent,
				ctlRect(getLeft() - buttonSize / 2, 0, buttonSize, buttonSize), "",
				ctlStyleGradient(stytype));
			_slider_button.setRelativeMoveFormat(ctlDirection::y, 0, 0, nullptr, this,
				moveAlignment::middle, moveAlignment::middle);
			ctlRect vr = getVirtualRect();
			_slider_button.setDragableDir(ctlDirection::x);
			_slider_button.setDragableRect(ctlRect(vr.getLeft(), 0, vr.getWidth(), 0));
		} else {
			_slider_button.create(parent,
				ctlRect(0, getBottom() - buttonSize / 2, buttonSize, buttonSize), "",
				ctlStyleGradient(stytype));
			_slider_button.setRelativeMoveFormat(ctlDirection::x, 0, 0, this, nullptr,
				moveAlignment::middle, moveAlignment::middle);
			ctlRect vr = getVirtualRect();
			_slider_button.setDragableDir(ctlDirection::y);
			_slider_button.setDragableRect(ctlRect(0, vr.getTop(), 0, vr.getHeight()));
		}
		_slider_button.addLambdaEvent(ctlNotifyEventType::drag, 
			[this](ctlRoot*, ctlNotifyEvent* ne)
			{
				ctlNotifyDrag* nd = reinterpret_cast<ctlNotifyDrag*>(ne->info);
				*nd->isAllow = false;
				if(getBarDirection() == ctlScrollDirection::horizontal)
				{
					setPercentProgress(static_cast<float>(
						nd->position.x - getLeft() + getButton()->getWidth() / 2) / getWidth());
				} else {	
					setPercentProgress(1.0f - static_cast<float>(
						nd->position.y - getTop() + getButton()->getHeight() / 2) / getHeight());
				}
			}); 
		setStyle(style);
		redraw();
		return true;
	}
	void ctlSlider::_mouse_event_(ctlMouseEvent* me)
	{
		if(me->eventModel != ctlMouseEventModel::cut) return;
		ctlProgress::_mouse_event_(me);
		if(me->eventType == ctlMouseEventType::leftDown)
		{
			if(getBarDirection() == ctlScrollDirection::horizontal)
			{
				setPercentProgress(
					static_cast<float>(me->mousePos.x)
					/ static_cast<float>(getWidth()));
			} else {
				setPercentProgress(
					1.0f - static_cast<float>(me->mousePos.y)
					/ static_cast<float>(getHeight()));
			}
		}
	}
	void ctlSlider::_position_event_(ctlPositionEvent* pe)
	{
		ctlProgress::_position_event_(pe);
		if(pe->eventType == ctlPositionEventType::size
			|| pe->eventType == ctlPositionEventType::move)
		{
			ctlRect vr = getVirtualRect();
			if(getBarDirection() == ctlScrollDirection::horizontal)
			{
				_slider_button.move(static_cast<int>(vr.getLeft()
					+ vr.getWidth() * getPercentProgress()), _slider_button.getTop());
				_slider_button.setDragableRect(ctlRect(vr.getLeft(), 0, vr.getWidth(), 0));
			} else {
				_slider_button.move(_slider_button.getLeft(), 
					static_cast<int>(vr.getTop()
					+ vr.getHeight() * (1.0f - getPercentProgress())));
				_slider_button.setDragableRect(ctlRect(0, vr.getTop(), 0, vr.getHeight()));
			}
		}
	}
	bool ctlSlider::setLogicProgress(int logicProgress)
	{
		if(ctlProgress::setLogicProgress(logicProgress))
		{
			ctlRect vr = getVirtualRect();
			if(getBarDirection() == ctlScrollDirection::horizontal)
			{
				_slider_button.move(static_cast<int>(vr.getLeft()
					+ getWidth() * getPercentProgress()), _slider_button.getTop());
			} else {
				_slider_button.move(_slider_button.getLeft(), 
					static_cast<int>(vr.getTop() + getHeight() * (1.0f - getPercentProgress())));
			}
			return true;
		}
		return false;
	}
	ctlButton* ctlSlider::getButton()
	{
		return &_slider_button;
	}
	ctlRect ctlSlider::getVirtualRect()
	{
		if(getBarDirection() == ctlScrollDirection::horizontal)
		{
			return ctlRect(getLeft() - getButton()->getWidth() / 2, 
				getTop() + ctlMin(0, (getHeight() - getButton()->getHeight()) / 2),
				getWidth() + getButton()->getWidth(), 
				ctlMax(getHeight(), getButton()->getHeight()));
		}
		return ctlRect(getLeft() + ctlMin(0, (getWidth() - getButton()->getWidth()) / 2), 
			getTop() - getButton()->getHeight() / 2,
			ctlMax(getWidth(), getButton()->getWidth()), 
			getHeight() + getButton()->getHeight());
	}
	bool ctlSlider::setZOrder(unsigned order)
	{
		if(ctlProgress::setZOrder(order))
		{
			getButton()->setZOrderAfter(this);
			return true;
		}
		return false;
	}
}